package com.emerquim.bean.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;

import com.emerquim.bean.dao.DepartamentosDAO;
import com.emerquim.bean.support.ControlDespliegue;
import com.emerquim.persistence.dao.PDepartamentoDAO;
import com.emerquim.persistence.dao.PEntidad;
import com.emerquim.persistence.dao.PEntidadDAO;
import com.emerquim.persistence.dao.PMunicipio;
import com.emerquim.persistence.dao.PMunicipioDAO;
import com.emerquim.persistence.dao.TipoReporta;
import com.emerquim.persistence.dao.TipoReportaDAO;
import com.icesoft.faces.context.effects.JavascriptContext;

public class Entidad {

	/**
	 * Funcionalidad de log
	 */
	private static final Logger log = Logger.getLogger(Entidad.class);

	/**
	 * Atributos de la Clase
	 */
	private int idEntidad;
	private String nombreEntidad;
	private int idDepartamento;
	private int idMunicipio;
	private String descripcionEntidad;
	private int idTipoReportante;
	private String direccionEntidad;
	private String telefonoEntidad;
	private String faxEntidad;
	private Integer nivelEntidad;
	private ArrayList<SelectItem> tiposReportante = new ArrayList<SelectItem>();

	public Entidad() {
		super();
		inicializarDatosNuevaEntidad();
	}

	/**
	 * @return the idEntidad
	 */
	public int getIdEntidad() {
		return idEntidad;
	}

	/**
	 * @param idEntidad
	 *            the idEntidad to set
	 */
	public void setIdEntidad(int idEntidad) {
		this.idEntidad = idEntidad;
	}

	/**
	 * @return the nombreEntidad
	 */
	public String getNombreEntidad() {
		return nombreEntidad;
	}

	/**
	 * @param nombreEntidad
	 *            the nombreEntidad to set
	 */
	public void setNombreEntidad(String nombreEntidad) {
		this.nombreEntidad = nombreEntidad;
	}

	/**
	 * @return the idDepartamento
	 */
	public int getIdDepartamento() {
		return idDepartamento;
	}

	/**
	 * @param idDepartamento
	 *            the idDepartamento to set
	 */
	public void setIdDepartamento(int idDepartamento) {
		this.idDepartamento = idDepartamento;
	}

	/**
	 * @return the idMunicipio
	 */
	public int getIdMunicipio() {
		return idMunicipio;
	}

	/**
	 * @param idMunicipio
	 *            the idMunicipio to set
	 */
	public void setIdMunicipio(int idMunicipio) {
		this.idMunicipio = idMunicipio;
	}

	/**
	 * @return the descripcionEntidad
	 */
	public String getDescripcionEntidad() {
		return descripcionEntidad;
	}

	/**
	 * @param descripcionEntidad
	 *            the descripcionEntidad to set
	 */
	public void setDescripcionEntidad(String descripcionEntidad) {
		this.descripcionEntidad = descripcionEntidad;
	}

	/**
	 * @return the idTipoReportante
	 */
	public int getIdTipoReportante() {
		return idTipoReportante;
	}

	/**
	 * @param idTipoReportante
	 *            the idTipoReportante to set
	 */
	public void setIdTipoReportante(int idTipoReportante) {
		this.idTipoReportante = idTipoReportante;
	}

	/**
	 * @return the direccionEntidad
	 */
	public String getDireccionEntidad() {
		return direccionEntidad;
	}

	/**
	 * @param direccionEntidad
	 *            the direccionEntidad to set
	 */
	public void setDireccionEntidad(String direccionEntidad) {
		this.direccionEntidad = direccionEntidad;
	}

	/**
	 * @return the telefonoEntidad
	 */
	public String getTelefonoEntidad() {
		return telefonoEntidad;
	}

	/**
	 * @param telefonoEntidad
	 *            the telefonoEntidad to set
	 */
	public void setTelefonoEntidad(String telefonoEntidad) {
		this.telefonoEntidad = telefonoEntidad;
	}

	/**
	 * @return the faxEntidad
	 */
	public String getFaxEntidad() {
		return faxEntidad;
	}

	/**
	 * @param faxEntidad
	 *            the faxEntidad to set
	 */
	public void setFaxEntidad(String faxEntidad) {
		this.faxEntidad = faxEntidad;
	}

	/**
	 * @return the nivelEntidad
	 */
	public Integer getNivelEntidad() {
		return nivelEntidad;
	}

	/**
	 * @param nivelEntidad
	 *            the nivelEntidad to set
	 */
	public void setNivelEntidad(Integer nivelEntidad) {
		this.nivelEntidad = nivelEntidad;
	}

	/**
	 * @return the tiposReportante
	 */
	public ArrayList<SelectItem> getTiposReportante() {
		return tiposReportante;
	}

	/**
	 * @param tiposReportante
	 *            the tiposReportante to set
	 */
	public void setTiposReportante(ArrayList<SelectItem> tiposReportante) {
		this.tiposReportante = tiposReportante;
	}

	public void inicializarDatosNuevaEntidad() {
		this.descripcionEntidad = "";
		this.direccionEntidad = "";
		this.faxEntidad = "";
		this.nivelEntidad = 1;
		this.idDepartamento = 11; // Bogota
		this.idMunicipio = 149; // Bogota
		this.idTipoReportante = 1;
		this.nombreEntidad = "";
		this.telefonoEntidad = "";
		obtenerTiposReportante();
	}

	/**
	 * Retorna la lista de municipios del departamento
	 * 
	 * @return ArrayList municipios
	 */
	public ArrayList<SelectItem> getMunicipiosEntidad() {
		ArrayList<SelectItem> municipios = new ArrayList<SelectItem>();
		FacesContext context = FacesContext.getCurrentInstance();
		DepartamentosDAO departamentosDAO = (DepartamentosDAO) context.getApplication().evaluateExpressionGet(context,
				"#{departamentosDAO}", DepartamentosDAO.class);
		if (departamentosDAO != null)
			municipios = departamentosDAO.getMunicipios(this.idDepartamento);
		return municipios;
	}
	
	/**
	 * Metodo para guardar una entidad
	 * 
	 * @return
	 */
	public void guardarEntidad() {
		// Hibernate...
		PEntidadDAO entidadDAO = new PEntidadDAO();
		PMunicipioDAO pMunicipioDAO = new PMunicipioDAO();
		TipoReportaDAO tiporeportaDAO = new TipoReportaDAO();
		PEntidad pEntidad = null;
		try {
			pEntidad = new PEntidad();
			pEntidad.setEntDesc(this.descripcionEntidad);
			pEntidad.setEntDir(this.direccionEntidad);
			pEntidad.setEntFax(this.faxEntidad);
			pEntidad.setEntNivel(this.nivelEntidad);
			pEntidad.setEntNom(this.nombreEntidad);
			pEntidad.setEntTels(this.telefonoEntidad);
			PMunicipio pMunicipio = pMunicipioDAO.findById(this.idMunicipio);
			pEntidad.setPMunicipioEntidad(pMunicipio);
			TipoReporta tipoReporta = tiporeportaDAO.findById(this.idTipoReportante);
			pEntidad.setTipoReporta(tipoReporta);
			entidadDAO.getSession().beginTransaction();
			entidadDAO.save(pEntidad);
			entidadDAO.getSession().getTransaction().commit();
			this.enviarMensajeUsuario("Se guardo exitosamente la entidad");
		} catch (HibernateException he) {
			log.error("Error al guardar la entidad en base de datos");
			he.printStackTrace();
		} finally {
			entidadDAO.getSession().close();
		}
	}

	/**
	 * Establece la lista tiposReportante con los valores de Items
	 * Seleccionados,
	 * 
	 */
	public void obtenerTiposReportante() {
		List<TipoReporta> lstTiposReportante;
		TipoReportaDAO tipoReportaDAO = new TipoReportaDAO();
		try {
			lstTiposReportante = tipoReportaDAO.findAll();
			// Se obtien un Iterador y recorre la lista.
			Iterator<TipoReporta> iter = lstTiposReportante.iterator();
			while (iter.hasNext()) {
				TipoReporta tr = new TipoReporta();
				tr = iter.next();
				this.tiposReportante.add(new SelectItem(tr.getTreId(), tr.getTreDesc()));
			}
		} catch (Exception e) {
			log.error("Error al listar los tipos de reportantes de la base de datos");
			e.printStackTrace();
		}
	}

	/**
	 * Metodo para enviar un mensaje de alerta el usuario
	 * 
	 * @param mensaje
	 * @author Felipe Criales
	 */
	private void enviarMensajeUsuario(String mensaje) {
		String funcion = "alert('" + mensaje + "');";
		JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(), funcion);
	}
	
	/**
	 * Agregar esta entidad en el evento
	 * @param evento
	 * @author Felipe Criales
	 */
	public void adicionarEntidadEvento(ActionEvent evento) {		
		// 1. Buscar el objeto de tipo evento y agregar la entidad
		FacesContext context = FacesContext.getCurrentInstance();
		Evento eventoObjeto = (Evento) context.getApplication().evaluateExpressionGet(
				context, "#{evento}", Evento.class);
		if (eventoObjeto != null) {
			eventoObjeto.adicionarEntidadAvisada(this, EntidadesInvolucradas.TIPO_ENTIDAD);			
		}
		
		// 2. Visualizar el panel de nuevo evento
		ControlDespliegue controlDespliegue = (ControlDespliegue) context.getApplication().evaluateExpressionGet(
				context, "#{controlDespliegue}", ControlDespliegue.class);
		if(controlDespliegue != null)
			controlDespliegue.setIndexTabPrincipal(ControlDespliegue.INDEX_TAB_EVENTO);
		
		// 3. Limpiar los datos de consulta
		ManejadorEntidades manejadorEntidades = (ManejadorEntidades) context.getApplication().evaluateExpressionGet(
				context, "#{manejadorEntidades}", ManejadorEntidades.class);
		if (manejadorEntidades != null) {
			manejadorEntidades.limpiarDatosConsulta();			
		}
	}
	
	/**
	 * Agregar esta entidad en el evento
	 * @param evento
	 * @author Felipe Criales
	 */
	public void adicionarOrganizacionAyudaEvento(ActionEvent evento) {		
		// 1. Buscar el objeto de tipo evento
		FacesContext context = FacesContext.getCurrentInstance();
		Evento eventoObjeto = (Evento) context.getApplication().evaluateExpressionGet(
				context, "#{evento}", Evento.class);
		if (eventoObjeto != null) {
			eventoObjeto.adicionarEntidadAvisada(this, EntidadesInvolucradas.TIPO_ORG_AYUDA);			
		}
		
		// 2. Visualizar el panel de nuevo evento
		ControlDespliegue controlDespliegue = (ControlDespliegue) context.getApplication().evaluateExpressionGet(
				context, "#{controlDespliegue}", ControlDespliegue.class);
		if(controlDespliegue != null)
			controlDespliegue.setIndexTabPrincipal(ControlDespliegue.INDEX_TAB_EVENTO);
		
		// 3. Limpiar los datos de consulta
		ManejadorEntidades manejadorEntidades = (ManejadorEntidades) context.getApplication().evaluateExpressionGet(
				context, "#{manejadorEntidades}", ManejadorEntidades.class);
		if (manejadorEntidades != null) {
			manejadorEntidades.limpiarDatosConsulta();			
		}
	}
	
	/**
	 * Agregar esta entidad en el evento
	 * @param evento
	 * @author Felipe Criales
	 */
	public void adicionarEntidadLLamoEvento(ActionEvent evento) {		
		// 1. Buscar el objeto de tipo evento
		FacesContext context = FacesContext.getCurrentInstance();
		Evento eventoObjeto = (Evento) context.getApplication().evaluateExpressionGet(
				context, "#{evento}", Evento.class);
		if (eventoObjeto != null) {
			eventoObjeto.adicionarEntidadAvisada(this, EntidadesInvolucradas.TIPO_ENTIDAD_LLAMO);			
		}
		
		// 2. Visualizar el panel de nuevo evento
		ControlDespliegue controlDespliegue = (ControlDespliegue) context.getApplication().evaluateExpressionGet(
				context, "#{controlDespliegue}", ControlDespliegue.class);
		if(controlDespliegue != null)
			controlDespliegue.setIndexTabPrincipal(ControlDespliegue.INDEX_TAB_EVENTO);
		
		// 3. Limpiar los datos de consulta
		ManejadorEntidades manejadorEntidades = (ManejadorEntidades) context.getApplication().evaluateExpressionGet(
				context, "#{manejadorEntidades}", ManejadorEntidades.class);
		if (manejadorEntidades != null) {
			manejadorEntidades.limpiarDatosConsulta();			
		}
	}
	
	/**
	 * Retorna el string del municipio
	 * @author Felipe Criales
	 */
	public String getMunicipioString(){
		PMunicipioDAO municipioDao = new PMunicipioDAO();
		try{			
			return municipioDao.findById(this.idMunicipio).getMunDesc(); 			
		} catch (HibernateException e) {
			municipioDao.getSession().close();
			log.error("Error al consultar el nombre del municipio", e);
		} finally {
			municipioDao.getSession().close();
		}
		return "";
	}
	
	/**
	 * Retorna el string del departamento
	 * @author Felipe Criales
	 */
	public String getDepartamentoString(){
		PDepartamentoDAO departamentoDao = new PDepartamentoDAO();
		try{			
			return departamentoDao.findById(this.idDepartamento).getDepDesc(); 			
		} catch (HibernateException e) {
			departamentoDao.getSession().close();
			log.error("Error al consultar el nombre del departamento", e);
		} finally {
			departamentoDao.getSession().close();
		}
		return "";
	}
	
	/**
	 * Retorna el string del departamento
	 * @author Felipe Criales
	 */
	public String getTipoReportanteString(){
		TipoReportaDAO tipoReportaDAO = new TipoReportaDAO();
		try{			
			return tipoReportaDAO.findById(this.idTipoReportante).getTreDesc();			
		} catch (HibernateException e) {
			tipoReportaDAO.getSession().close();
			log.error("Error al consultar el nombre del departamento", e);
		} finally {
			tipoReportaDAO.getSession().close();
		}
		return "";
	}
}
